/*****************************
 *  -----------------------  *
 * DRobot (Take the Control) *
 *  -----------------------  *
 *****************************/
package com.drobot.screen;

import java.awt.AWTException;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;

import com.drobot.Drobot;

/**
 * @author jhornola
 * 
 */
/**
 * @author jhornola
 *
 */
public class Screen {
	private final int destkopWidth;
	private final int destkopHeight;
	private final Robot robot;

	public Screen(Robot robot) {
		this.robot = robot;
		destkopWidth = Toolkit.getDefaultToolkit().getScreenSize().width;
		destkopHeight = Toolkit.getDefaultToolkit().getScreenSize().height;
	}

	/**
	 * Metodo que devuelve el ancho de la pantalla, medido en pixeles.
	 * 
	 * @return El ancho de la pantalla.
	 */
	public int getDestkopWidth() {
		return destkopWidth;
	}

	/**
	 * Metodo que devuelve el alto de la pantalla, medido en pixeles.
	 * 
	 * @return El alto de la pantalla.
	 */
	public int getDestkopHeight() {
		return destkopHeight;
	}

	/**
	 * Metodo que realiza una impresion de la pantalla.
	 * 
	 * @return La imagen de la pantalla.
	 */
	public BufferedImage getScreen() {
		return getScreen(new Rectangle(0, 0, destkopWidth, destkopHeight));
	}

	/**
	 * Metodo que realiza una impresion de una region de la pantalla.
	 * 
	 * @param rectangle
	 *            La region que se desea capturar.
	 * @return La imagen de la region.
	 */
	public BufferedImage getScreen(Rectangle rectangle) {
		return robot.createScreenCapture(rectangle);
	}

	/**
	 * @see compare(Pixel pixel, int delta, BufferedImage image)
	 */
	public boolean compare(Pixel pixel) {
		return compare(pixel, 0, getScreen());
	}

	/**
	 * @see compare(Pixel pixel, int delta, BufferedImage image)
	 */
	public boolean compare(Pixel pixel, int delta) {
		return compare(pixel, delta, getScreen());
	}

	/**
	 * @see compare(Pixel pixel, int delta, BufferedImage image)
	 */
	public boolean compare(Pixel pixel, BufferedImage image) {
		return compare(pixel, 0, image);
	}

	/**
	 * Compara el color del pixel con su semejante en la imagen, permitendo una desviacion delta.
	 * 
	 * @param pixel
	 *            El pixel que se desea comparar.
	 * @param delta
	 *            La desviacion maxima permitida <i>(0-255)</i>.
	 * @param image
	 *            la imagen en la que se realizara la comparacion.
	 */
	public boolean compare(Pixel pixel, int delta, BufferedImage image) {
		Pixel other = new Pixel(pixel.x, pixel.y, image);
		if (other.equals(pixel, delta))
			return true;
		return false;
	}

	public boolean compare(PixelChecksum checksum) {
		PixelChecksum other = new PixelChecksum(checksum.left, checksum.top, checksum.right, checksum.bottom,
				getScreen());
		if (other.equals(checksum))
			return true;
		return false;
	}

	public boolean compare(PixelChecksum checksum, BufferedImage image) {
		PixelChecksum other = new PixelChecksum(checksum.left, checksum.top, checksum.right, checksum.bottom, image);
		if (other.equals(checksum))
			return true;
		return false;
	}

	public Pixel search(Pixel pixel, Rectangle rectangle) {
		return search(pixel, rectangle, 0, getScreen());
	}

	public Pixel search(Pixel pixel, Rectangle rectangle, int delta) {
		return search(pixel, rectangle, delta, getScreen());
	}

	/**
	 * Busca el color de un pixel en la region especificada, permitendo una desviacion delta.
	 * @param pixel
	 * @param rectangle
	 * @param delta
	 * @param image
	 * @return
	 */
	public Pixel search(Pixel pixel, Rectangle rectangle, int delta, BufferedImage image) {
		for (int x = rectangle.x; x < rectangle.width; x++) {
			for (int y = rectangle.y; y < rectangle.height; y++) {
				if (new Pixel(x, y, image).equals(pixel, delta)) {
					return new Pixel(x, y, image);
				}
			}
		}
		return null;
	}

	/**
	 * Pausa la aplicacion hasta que el pixel no de la pantalla no cambie de color.
	 * 
	 * @param pixel El pixel observado.
	 */
	public void waitPixel(Pixel pixel) {
		while (!compare(pixel)) {
			Drobot.Control.sleep(50);
		}
	}
	
	/**
	 * Pausa la aplicacion hasta que el pixel no de la pantalla no cambie de color.
	 * 
	 * @param pixel El pixel observado.
	 */
	public void waitChange(Pixel pixel) {
		Pixel pixelScreen = new Pixel(pixel.x, pixel.y, getScreen());
		while (pixel.equals(pixelScreen)) {
			Drobot.Control.sleep(50);
		}
	}

}
